package client;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import view.JanelaDeConversa;
import model.Configuracao;
import model.Contato;
import model.MensagemDeArquivo;
import model.MensagemDeTexto;
import model.RecebivelPorConversa;

public class Conversa{
	
	private RecebivelPorConversa mensagemRecebida; //este atributo é só para mensagens recebidas.
	public final static boolean MENSAGEM_DE_TEXTO = true;
	public final static boolean MENSAGEM_DE_ARQUIVO = false;
	
	private Contato contatoDestino;
	private String ipDestino;
	private Socket socket;
	
	private String caminhoArquivo; //caminho onde sera salvo o arquivo recebido
	
	private JanelaDeConversa janela;
	
	//Construtor usado quando eu tiver recebido uma mensagem para iniciar uma conversa.
	public Conversa(RecebivelPorConversa mensagem, JanelaDeConversa janela){
		this.janela = janela;
		trataMensagemRecebida(mensagem);
	}
	
	public void trataMensagemRecebida(RecebivelPorConversa mensagem){
		this.mensagemRecebida = mensagem;
		this.ipDestino = mensagem.getIpRemetente();
		
		if(mensagem instanceof MensagemDeTexto)
			trataMensagemTexto();
		else
			trataMensagemArquivo();
	}
	
	//Construtor usado para quem iniciará uma nova conversa.
	public Conversa(Contato contatoDestino, String ipDestino, JanelaDeConversa janela){
		this.setContatoDestino(contatoDestino);
		this.ipDestino = ipDestino;
		this.janela = janela;
		System.out.println("Nova conversa criada, destinatário: " + contatoDestino.getLogin() + " ip: " + ipDestino);
	}

	
	
	private void trataMensagemTexto(){
		//System.out.println("Mensagem de texto recebida: " + ((MensagemDeTexto)mensagemRecebida).getMensagemTexto());
		this.janela.atualizaConversas(Conversa.MENSAGEM_DE_TEXTO);
	}
	
	private void trataMensagemArquivo(){
		mensagemRecebida = (MensagemDeArquivo) mensagemRecebida;
		if (aprovaRecebimentoArquivo()) {
			try {
				salvaArquivo((MensagemDeArquivo) mensagemRecebida);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				System.out.println("Erro ao salvar arquivo!");
				e.printStackTrace();
			}
			this.janela.atualizaConversas(Conversa.MENSAGEM_DE_ARQUIVO );
			System.out.println("Arquivo salvo com sucesso!");
		}
		else
			System.out.println("Arquivo: " + ((MensagemDeArquivo) mensagemRecebida).getNomeArquivo() + " rejeitado!");
	}
		
	//Envia uma solicitacao de recebimento de arquivo
	//Como faço para este método funcionar junto com a interface gráfica de forma independente?
	//Não é bom que funcione dependendo da interface. Procurar uma solução.
	private boolean aprovaRecebimentoArquivo(){
		int resposta;
		resposta = javax.swing.JOptionPane.showConfirmDialog(null, "Deseja receber o arquivo: " + 
				((MensagemDeArquivo) mensagemRecebida).getNomeArquivo(), 
				"Transferencia de Dados", javax.swing.JOptionPane.OK_CANCEL_OPTION,
				javax.swing.JOptionPane.QUESTION_MESSAGE);
		
		if (resposta == javax.swing.JOptionPane.YES_OPTION){
			this.caminhoArquivo = javax.swing.JOptionPane.showInputDialog("Digite o caminho e o nome em que o arquivo será salvo:");
			return true;
		}	
		else
			return false;
	}

			
	private void salvaArquivo(MensagemDeArquivo mensagem) throws IOException{
		
		try {
			FileOutputStream arquivoSaida = new FileOutputStream(caminhoArquivo);
			BufferedOutputStream fluxoSaida = new BufferedOutputStream(arquivoSaida);
			System.out.println("Buffer de saída para gravacao no HD criado.");
			fluxoSaida.write(mensagem.getBuf());
			
			System.out.println("Arquivo armazenado em: " + caminhoArquivo);
			caminhoArquivo = null;
			
			//Fecha conexões de saída
			try {
				fluxoSaida.flush();
				fluxoSaida.close();
				arquivoSaida.close();

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("Erro ao fechar fluxos.");
			}
			
		} catch (FileNotFoundException e) {
			System.out.println("Erro ao salvar arquivo.");
			e.printStackTrace();
		}
	}
	
	//Para uso do GUI
	public void enviaMensagem(String conteudo, boolean tipo) throws UnknownHostException, IOException{
		
		RecebivelPorConversa mensagemSaida = null;
		
		if (tipo == MENSAGEM_DE_TEXTO){
			mensagemSaida = new MensagemDeTexto(conteudo);
			System.out.println("conteudo a ser enviado, convertido num objeto mensagem de texto.");
		}
		else{
			mensagemSaida = new MensagemDeArquivo(conteudo);
			System.out.println("conteudo a ser enviado, convertido num objeto mensagem de arquivo.");			
		}
		
		mensagemSaida.setIpDestino(ipDestino);
		mensagemSaida.setIpRemetente(InetAddress.getLocalHost().getHostAddress());
		
		socket = new Socket(ipDestino, Configuracao.PORTA_COMUNICACAO);
		System.out.println("Socket para envio criado, IP: " + ipDestino + " porta: " + Configuracao.PORTA_COMUNICACAO);
		enviaMensagem(mensagemSaida); 
		socket.close();
	}

	
	private void enviaMensagem(RecebivelPorConversa msg) throws UnknownHostException, IOException{
		System.out.println("Conexão com o cliente para envio de dados feita.");
		ObjectOutputStream fluxo = new ObjectOutputStream(socket.getOutputStream());
		System.out.println("Fluxo de envio criado.");
		//envia o objeto mensagem serializado
		fluxo.writeObject(msg);
		System.out.println("Serializou mensagem e a enviou.");
	}


	public void setIpDestino(String ipDestino) {
		this.ipDestino = ipDestino;
	}


	public String getIpDestino() {
		return ipDestino;
	}
	
	public String getConteudoTextoRecebido(){
		return ((MensagemDeTexto)mensagemRecebida).getMensagemTexto();
	}
	
	public String getConteudoArquivoRecebido(){
		return ((MensagemDeArquivo)mensagemRecebida).getNomeArquivo();
	}

	public void setContatoDestino(Contato contatoDestino) {
		this.contatoDestino = contatoDestino;
	}

	public Contato getContatoDestino() {
		return contatoDestino;
	}
		
	public void setJanela(JanelaDeConversa janela){
		this.janela = janela;
	}
	
	

}
